%%% job_maintenance.erl

%%% Tasks and Completed Tasks are an Erlang Dictionary
%%% When a completed task is received by the process, it removes the entry from tasks and adds it to the completed tasks

-module(job_maintenance).
-export([hold_info/7]).

hold_info({SC_Filename, SC_Ext} , {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution, distribute) 
        when (Percent_Complete => 0.49, Percent_Complete < 0.51);
             (Percent_Complete => 0.79, Percent_Complete < 0.81);
             (Percent_Complete => 0.89, Percent_Complete < 0.91) ->

    server_utils:send_messages(list_to_atom("work" ++ atom_to_list(server_utils:get_process_name(self()))), [{redistribute, {Tasks}}]),
    hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution, 'receive');

hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution, 'receive') ->
	receive
        {receive_task, {Task_ID, Result}} ->
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, dict:erase(Task_ID, Tasks), 
                      dict:append(Task_ID, Result, Completed_Tasks), (1/dict:size(dict:erase(Task_ID,Tasks))), Solution, distribute);

		{request, {server_code_path, server_code_ext}, {worker_code_path, worker_code_ext}, {tasks}, Requester} ->
            server_utils:send_messages(Requester, {ack, {SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, {Tasks}}),
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution);

        {request, {worker_code_path, worker_code_ext}, Requester} ->
            server_utils:send_messages(Requester, [{ack, {WC_Filename, WC_Ext}}]),
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution);

		{request, {solution}, Client, Client_Proc} when length(Tasks) == length(Completed_Tasks) ->
			{Listen_Socket, Address, Port} = server_utils:open_socket(0),
            {ok, Send_Socket} = gen_tcp:accept(Listen_Socket),
            ok = server_utils:send_data(Send_Socket, zlib:zip(New_Solution)),
            ok = server_utils:close_socket(Send_Socket),
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution);

        {request, {solution}, Client, Client_Proc} ->
            server_utils:send_messages({Client, Client_Proc}, [{solution, length(Completed_Tasks)/length(Tasks)}]),
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution);

        {request, {server_code_path, server_code_extension}, Requester} ->
            server_utils:send_messages(Requester, [{ack, SC_Filename, SC_Ext}]),
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, Solution);

        {receive_solution, {Address, Port}, Sender} ->
            {ok, Receive_Socket} =  gen_tcp:connect(Socket, Address, [binary, {packet, 4}]), %TODO extract connect code to utility module
            {ok, New_Solution}   = server_utils:receive_data(Receive_Socket, zipped),
            ok = server_utils:send_messages(Sender, [solution_received]),
            hold_info({SC_Filename, SC_Ext}, {WC_Filename, WC_Ext}, Tasks, Completed_Tasks, Percent_Complete, New_Solution)

	end.
